package com.v9.common.config;

import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import org.springdoc.core.customizers.ActuatorOperationCustomizer;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class OpenapiConfiguration implements WebMvcConfigurer {

    @Bean("openapi")
    public OpenAPI springShopOpenAPI() {
        return new OpenAPI()
                .info(new Info().title("SpringShop API")
                        .description("Spring shop sample application")
                        .version("v0.0.1")
                        .license(new License().name("Apache 2.0").url("http://springdoc.org")))
                .externalDocs(new ExternalDocumentation()
                        .description("SpringShop Wiki Documentation")
                        .url("https://springshop.wiki.github.org/docs"));
    }

    @Bean
    public ActuatorOperationCustomizer actuatorOperationCustomizer(){
        return new ActuatorOperationCustomizer() {
            @Override
            public Operation customize(Operation operation, HandlerMethod handlerMethod) {
                Operation customize = super.customize(operation, handlerMethod);
                ApiResponses responses = customize.getResponses();
                Content content = responses.get("200").getContent();
                if (responses == null || responses.get("200") == null || content == null) {
                    ApiResponse value = new ApiResponse();
                    content = new Content();
                    MediaType mediaType = new MediaType();
                    Schema schema = new Schema();
                    schema.setType("object");
                    schema.setProperties(new HashMap<>());

                    BooleanSchema booleanSchema = new BooleanSchema();
                    booleanSchema.setDefault(true);
                    booleanSchema.setDescription("执行状态,成功返回 true,错误返回 false");
                    schema.getProperties().put("success",booleanSchema);


                    StringSchema codeSchema=new StringSchema();
                    codeSchema.setDescription("消息编码");
                    schema.getProperties().put("code",codeSchema);

                    StringSchema messageSchema =new StringSchema();
                    messageSchema.setDescription("错误消息");
                    schema.getProperties().put("message", messageSchema);

                    mediaType.setSchema(schema);
                    content.put("*/*", mediaType);
                    value.setContent(content);
                    responses.put("200", value);
                    return customize;
                }
                if (content.get("*/*") == null) {
                    return customize;
                }
                MediaType mediaType = content.get("*/*");
                Schema schema = new Schema();
                schema.setType("object");
                schema.setProperties(new HashMap<>());

                BooleanSchema booleanSchema = new BooleanSchema();
                booleanSchema.setDefault(true);
                booleanSchema.setDescription("执行状态,成功返回 true,错误返回 false");
                schema.getProperties().put("success",booleanSchema);

                StringSchema codeSchema=new StringSchema();
                codeSchema.setDescription("消息编码");
                schema.getProperties().put("code",codeSchema);

                StringSchema messageSchema=new StringSchema();
                messageSchema.setDescription("错误消息");
                schema.getProperties().put("message", messageSchema);
                schema.getProperties().put("data",mediaType.getSchema());
                mediaType.setSchema(schema);
                return customize;
            }
        };
    }

    @Bean
    public OpenApiCustomiser openApiCustomiser() {
        return openApi -> {
            Map<String, Schema> schemas = openApi.getComponents().getSchemas();
            if (schemas == null) {
                return;
            }
            schemas.remove("PageableObject");
            schemas.remove("Sort");
            openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> {
                ApiResponses apiResponses = operation.getResponses();
                Content content = new Content();
                MediaType mediaType = new MediaType();
                Map<String, Schema> schemaList = new HashMap();
                schemas.forEach((k, item) -> {
                    Map properties = item.getProperties();
                    if (properties == null) {
                        return;
                    }
                    Object totalElements = properties.get("totalElements");
                    Object content1 = properties.get("content");
                    if (totalElements != null && content1 != null) {
                        properties.put("pageIndex", properties.get("number"));
                        properties.put("list", properties.get("content"));
                        properties.put("totalCount", properties.get("numberOfElements"));
                        properties.put("pageSize", properties.get("size"));
                        properties.remove("totalElements");
                        properties.remove("content");
                        properties.remove("numberOfElements");
                        properties.remove("sort");
                        properties.remove("size");
                        properties.remove("last");
                        properties.remove("first");
                        properties.remove("number");
                        properties.remove("empty");
                        properties.remove("pageable");
                    }
                });
                schemas.putAll(schemaList);
                content.addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, mediaType);
                HashMap<String, Object> extensions = new HashMap<>();
                extensions.put("ddd", true);
                ApiResponse apiResponse = new ApiResponse().description("Common Unauthorized Error").content(content).extensions(extensions);

                ApiResponse notFoundApiResponse = new ApiResponse().description("Common Not Found Error").content(content);
                apiResponses.addApiResponse(String.valueOf(HttpStatus.UNAUTHORIZED.value()), apiResponse);
                apiResponses.addApiResponse(String.valueOf(HttpStatus.NOT_FOUND.value()), notFoundApiResponse);

            }));
        };
    }
}
